unit Helpers.DateTime;

interface

uses
  System.SysUtils, System.DateUtils;

type
  TDateTimeHelper = record helper for TDateTime
  public
    function DateOf: TDate; inline;
    function TimeOf: TTime; inline;
    function ToString: string; inline;
    function Format(const pMascara: string): string; inline;

    class function EncodeDateTime(const pAno: UInt16; const pMes: UInt8; const pDia: UInt8; const pHora: UInt8;
      const pMinuto: UInt8; const pSegundo: UInt8; const pMilissegundo: UInt16): TDateTime; static;
    class function EncodeDate(const pAno: UInt16; const pMes: UInt8; const pDia: UInt8): TDateTime; static;
    class function EncodeTime(const pHora: UInt8; const pMinuto: UInt8; const pSegundo: UInt8;
      const pMilissegundo: UInt16): TDateTime; static;

    procedure DecodeDateTime(out pAno: UInt16; out pMes: UInt8; out pDia: UInt8; out pHora: UInt8; out pMinuto: UInt8;
      out pSegundo: UInt8; out pMilissegundo: UInt16);
    procedure DecodeDate(out pAno: Word; out pMes: Byte; out pDia: Byte);
    procedure DecodeTime(out pHora: UInt8; out pMinuto: UInt8; out pSegundo: UInt8; out pMilissegundo: UInt16);

    function YearOf: UInt16; inline;
    function MonthOf: UInt8; inline;
    function DayOf: UInt8; inline;
    function HourOf: UInt8; inline;
    function MinuteOf: UInt8; inline;
    function SecondOf: UInt8; inline;
    function MilliSecondOf: UInt16; inline;

    function YearsBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function MonthsBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function DaysBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function HoursBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function MinutesBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function SecondsBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function MillisecondsBetween(const pComparandoComDataEHora: TDateTime): Int64;
  end;

  TDateHelper = record helper for TDate
  strict private
    function ToDateTime: TDateTime;
  public
    function ToString: string;
    function Format(const pMascara: string): string;

    class function EncodeDate(const pAno: UInt16; const pMes: UInt8; const pDia: UInt8): TDateTime; static;

    procedure DecodeDate(out pAno: Word; out pMes: Byte; out pDia: Byte);

    function YearOf: UInt16;
    function MonthOf: UInt8;
    function DayOf: UInt8;

    function YearsBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function MonthsBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function DaysBetween(const pComparandocomDataEhora: TDateTime): Int32;
  end;

  TTimeHelper = record helper for TTime
  strict private
    function ToDateTime: TDateTime;
  public
    function ToString: string;
    function Format(const pMascara: string): string;

    class function EncodeTime(const pHora: UInt8; const pMinuto: UInt8; const pSegundo: UInt8;
      const pMilissegundo: UInt16): TDateTime; static;

    procedure DecodeTime(out pHora: UInt8; out pMinuto: UInt8; out pSegundo: UInt8; out pMilissegundo: UInt16);

    function HourOf: UInt8;
    function MinuteOf: UInt8;
    function SecondOf: UInt8;
    function MilliSecondOf: UInt16;

    function HoursBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function MinutesBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function SecondsBetween(const pComparandoComDataEHora: TDateTime): Int32;
    function MillisecondsBetween(const pComparandoComDataEHora: TDateTime): Int64;
  end;

implementation

{ TDateTimeHelper }

function TDateTimeHelper.DateOf: TDate;
begin
  Result := System.DateUtils.DateOf(Self);
end;

function TDateTimeHelper.DayOf: UInt8;
begin
  Result := System.DateUtils.DayOf(Self);
end;

function TDateTimeHelper.DaysBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := System.Trunc(Self - pComparandoComDataEHora);
end;

procedure TDateTimeHelper.DecodeDate(out pAno: Word; out pMes, pDia: Byte);
var
  lAno: Word;
  lMes: Word;
  lDia: Word;
begin
  System.SysUtils.DecodeDate(Self, lAno, lMes, lDia);

  pAno := lAno;
  pMes := lMes;
  pDia := lDia;
end;

procedure TDateTimeHelper.DecodeDateTime(out pAno: UInt16; out pMes, pDia, pHora, pMinuto, pSegundo: UInt8;
  out pMilissegundo: UInt16);
var
  lAno: Word;
  lMes: Word;
  lDia: Word;
  lHora: Word;
  lMinuto: Word;
  lSegundo: Word;
  lMilissegundo: Word;
begin
  System.DateUtils.DecodeDateTime(Self, lAno, lMes, lDia, lHora, lMinuto, lSegundo, lMilissegundo);

  pAno := lAno;
  pMes := lMes;
  pDia := lDia;
  pHora := lHora;
  pMinuto := lMinuto;
  pSegundo := lSegundo;
  pMilissegundo := lMilissegundo;
end;

procedure TDateTimeHelper.DecodeTime(out pHora, pMinuto, pSegundo: UInt8; out pMilissegundo: UInt16);
var
  lHora: Word;
  lMinuto: Word;
  lSegundo: Word;
  lMilissegundo: Word;
begin
  System.SysUtils.DecodeTime(Self, lHora, lMinuto, lSegundo, lMilissegundo);

  pHora := lHora;
  pMinuto := lMinuto;
  pSegundo := lSegundo;
  pMilissegundo := lMilissegundo;
end;

class function TDateTimeHelper.EncodeDate(const pAno: UInt16; const pMes, pDia: UInt8): TDateTime;
begin
  Result := System.SysUtils.EncodeDate(pAno, pMes, pDia);
end;

class function TDateTimeHelper.EncodeDateTime(const pAno: UInt16; const pMes, pDia, pHora, pMinuto, pSegundo: UInt8;
  const pMilissegundo: UInt16): TDateTime;
begin
  Result := System.DateUtils.EncodeDateTime(pAno, pMes, pDia, pHora, pMinuto, pSegundo, pMilissegundo);
end;

class function TDateTimeHelper.EncodeTime(const pHora, pMinuto, pSegundo: UInt8;
  const pMilissegundo: UInt16): TDateTime;
begin
  Result := System.SysUtils.EncodeTime(pHora, pMinuto, pSegundo, pMilissegundo);
end;

function TDateTimeHelper.Format(const pMascara: string): string;
begin
  Result := System.SysUtils.FormatDateTime(pMascara, Self);
end;

function TDateTimeHelper.HourOf: UInt8;
begin
  Result := System.DateUtils.HourOf(Self);
end;

function TDateTimeHelper.HoursBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := System.Trunc((Self - pComparandoComDataEHora) / OneHour);
end;

function TDateTimeHelper.MilliSecondOf: UInt16;
begin
  Result := System.DateUtils.MilliSecondOf(Self);
end;

function TDateTimeHelper.MillisecondsBetween(const pComparandoComDataEHora: TDateTime): Int64;
begin
  Result := System.Trunc((Self - pComparandoComDataEHora) / OneMillisecond);
end;

function TDateTimeHelper.MinuteOf: UInt8;
begin
  Result := System.DateUtils.MinuteOf(Self);
end;

function TDateTimeHelper.MinutesBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := System.Trunc((Self - pComparandoComDataEHora) / OneMinute);
end;

function TDateTimeHelper.MonthOf: UInt8;
begin
  Result := System.DateUtils.MonthOf(Self);
end;

function TDateTimeHelper.MonthsBetween(const pComparandoComDataEHora: TDateTime): Int32;
var
  lAno: UInt16;
  lMes: UInt8;
  lDia: UInt8;
  lHora: UInt8;
  lMinuto: UInt8;
  lSegundo: UInt8;
  lMilissegundo: UInt16;
  lAnoComparacao: UInt16;
  lMesComparacao: UInt8;
  lDiaComparacao: UInt8;
  lHoraComparacao: UInt8;
  lMinutoComparacao: UInt8;
  lSegundoComparacao: UInt8;
  lMilissegundoComparacao: UInt16;
  lData: TDateTime;
  lDataComparacao: TDateTime;
begin
  if Self <> pComparandoComDataEHora then
  begin
    DecodeDateTime(lAno, lMes, lDia, lHora, lMinuto, lSegundo, lMilissegundo);
    pComparandoComDataEHora.DecodeDateTime(lAnoComparacao, lMesComparacao, lDiaComparacao, lHoraComparacao,
      lMinutoComparacao, lSegundoComparacao, lMilissegundoComparacao);

    Result := ((lAno - lAnoComparacao) * MonthsPerYear) + (lMes - lMesComparacao);

    if Result <> 0 then
    begin
      lData := EncodeDateTime(1, 1, lDia, lHora, lMinuto, lSegundo, lMilissegundo);
      lDataComparacao := TDateTime.EncodeDateTime(1, 1, lDiaComparacao, lHoraComparacao, lMinutoComparacao, lSegundoComparacao,
        lMilissegundoComparacao);

      if (lData > lDataComparacao) and (Self < pComparandoComDataEHora) then
      begin
        Inc(Result);
      end else
      if (lData < lDataComparacao) and (Self > pComparandoComDataEHora) then
      begin
        Dec(Result);
      end;
    end;
  end else begin
    Result := 0;
  end;
end;

function TDateTimeHelper.SecondOf: UInt8;
begin
  Result := System.DateUtils.SecondOf(Self);
end;

function TDateTimeHelper.SecondsBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := System.Trunc((Self - pComparandoComDataEHora) / OneSecond);
end;

function TDateTimeHelper.TimeOf: TTime;
begin
  Result := System.DateUtils.TimeOf(Self);
end;

function TDateTimeHelper.ToString: string;
begin
  Result := System.SysUtils.DateToStr(Self);
end;

function TDateTimeHelper.YearOf: UInt16;
begin
  Result := System.DateUtils.YearOf(Self);
end;

function TDateTimeHelper.YearsBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := Self.MonthsBetween(pComparandoComDataEHora) div 12;
end;

{ TDateHelper }

function TDateHelper.DayOf: UInt8;
begin
  Result := Self.ToDateTime.DayOf;
end;

function TDateHelper.DaysBetween(const pComparandocomDataEhora: TDateTime): Int32;
begin
  Result := Self.ToDateTime.DaysBetween(pComparandoComDataEHora);
end;

procedure TDateHelper.DecodeDate(out pAno: Word; out pMes, pDia: Byte);
begin
  Self.ToDateTime.DecodeDate(pAno, pMes, pDia);
end;

class function TDateHelper.EncodeDate(const pAno: UInt16; const pMes, pDia: UInt8): TDateTime;
begin
  Result := TDateTime.EncodeDate(pAno, pMes, pDia);
end;

function TDateHelper.Format(const pMascara: string): string;
begin
  Result := Self.ToDateTime.Format(pMascara);
end;

function TDateHelper.MonthOf: UInt8;
begin
  Result := Self.ToDateTime.MonthOf;
end;

function TDateHelper.MonthsBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := Self.ToDateTime.MonthsBetween(pComparandoComDataEHora);
end;

function TDateHelper.ToDateTime: TDateTime;
begin
  Result := System.DateUtils.DateOf(Self);
end;

function TDateHelper.ToString: string;
begin
  Result := Self.ToDateTime.ToString;
end;

function TDateHelper.YearOf: UInt16;
begin
  Result := Self.ToDateTime.YearOf;
end;

function TDateHelper.YearsBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := Self.ToDateTime.YearsBetween(pComparandoComDataEHora);
end;

{ TTimeHelper }

procedure TTimeHelper.DecodeTime(out pHora, pMinuto, pSegundo: UInt8; out pMilissegundo: UInt16);
begin
  Self.ToDateTime.DecodeTime(pHora, pMinuto, pSegundo, pMilissegundo);
end;

class function TTimeHelper.EncodeTime(const pHora, pMinuto, pSegundo: UInt8; const pMilissegundo: UInt16): TDateTime;
begin
  Result := TDateTime.EncodeTime(pHora, pMinuto, pSegundo, pMilissegundo);
end;

function TTimeHelper.Format(const pMascara: string): string;
begin
  Result := Self.ToDateTime.Format(pMascara);
end;

function TTimeHelper.HourOf: UInt8;
begin
  Result := Self.ToDateTime.HourOf;
end;

function TTimeHelper.HoursBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := Self.ToDateTime.HoursBetween(pComparandoComDataEHora);
end;

function TTimeHelper.MilliSecondOf: UInt16;
begin
  Result := Self.ToDateTime.MilliSecondOf;
end;

function TTimeHelper.MillisecondsBetween(const pComparandoComDataEHora: TDateTime): Int64;
begin
  Result := Self.ToDateTime.MillisecondsBetween(pComparandoComDataEHora);
end;

function TTimeHelper.MinuteOf: UInt8;
begin
  Result := Self.ToDateTime.MinuteOf;
end;

function TTimeHelper.MinutesBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := Self.ToDateTime.MinutesBetween(pComparandoComDataEHora);
end;

function TTimeHelper.SecondOf: UInt8;
begin
  Result := Self.ToDateTime.SecondOf;
end;

function TTimeHelper.SecondsBetween(const pComparandoComDataEHora: TDateTime): Int32;
begin
  Result := Self.ToDateTime.SecondsBetween(pComparandoComDataEHora);
end;

function TTimeHelper.ToDateTime: TDateTime;
begin
  Result := System.DateUtils.TimeOf(Self);
end;

function TTimeHelper.ToString: string;
begin
  Result := Self.ToDateTime.ToString;
end;

end.
